package com.nb.cloud.doc.biz.impl;

import cn.hutool.core.bean.BeanUtil;
import com.nb.cloud.doc.biz.ISearchBiz;
import com.nb.cloud.doc.constant.ESConstant;
import com.nb.cloud.doc.enums.GradeEnum;
import com.nb.cloud.doc.enums.TermEnum;
import com.nb.cloud.doc.model.PageVO;
import com.nb.cloud.doc.model.dto.SearchDTO;
import com.nb.cloud.doc.model.vo.SearchListVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author lihaoyang6
 * @date 2024年08月10日 12:58
 */
@Slf4j
@Service
public class SearchBizImpl implements ISearchBiz {

    @Autowired
    RestHighLevelClient client;

    @Override
    public PageVO<SearchListVO> search(SearchDTO searchDTO) {
        // 创建SearchRequest
        SearchRequest searchRequest = new SearchRequest(ESConstant.DOC_INDEX);
        // 创建SearchSourceBuilder
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 设置分页
        searchSourceBuilder.from(searchDTO.getPageNo()-1);
        searchSourceBuilder.size(searchDTO.getPageSize());

        // 设置需要返回的字段
        String[] fields = {"id", "documentId", "title", "description", "docType", "coverImage", "difficulty", "subjectCode", "subjectName", "grade", "term", "textbookVersionId", "chapterId", "status", "deleteFlag"};
        FetchSourceContext fetchSourceContext = new FetchSourceContext(true, fields, null);
        searchSourceBuilder.fetchSource(fetchSourceContext);

        // 创建bool查询
        org.elasticsearch.index.query.BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 添加filter条件
        boolQueryBuilder.filter(QueryBuilders.termQuery("deleteFlag", 0));
        if(StringUtils.isNotBlank(searchDTO.getTextbookVersionId())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("textbookVersionId", searchDTO.getTextbookVersionId()));
        }
        if(Objects.nonNull(searchDTO.getTerm())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("term", searchDTO.getTerm()));
        }
        if(Objects.nonNull(searchDTO.getSubjectCode())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("subjectCode", searchDTO.getSubjectCode()));
        }
        if(Objects.nonNull(searchDTO.getGrade())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("grade", searchDTO.getGrade()));
        }
        // 添加must条件
        if(StringUtils.isNotBlank(searchDTO.getKeyword())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("description",searchDTO.getKeyword() ));
        }
        // 将bool查询设置为查询条件
        searchSourceBuilder.query(boolQueryBuilder);

        // 将SearchSourceBuilder设置到SearchRequest
        searchRequest.source(searchSourceBuilder);
        List<SearchListVO> records = new ArrayList<>();
        // 执行查询
        long total = 0;
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            total = searchResponse.getHits().getTotalHits().value;
            // 处理响应（这里只是简单打印结果数量）
            System.out.println("Total Hits: " + total);
            for (SearchHit hit : searchResponse.getHits().getHits()) {
                Map<String, Object> sourceMap = hit.getSourceAsMap();
                SearchListVO listVO = new SearchListVO();
                BeanUtil.fillBeanWithMapIgnoreCase(sourceMap, listVO, true);
                System.out.println(hit.getSourceAsString());
                listVO.setGradeName(GradeEnum.getByCode(listVO.getGrade()).getText());
                listVO.setTermName(TermEnum.getByCode(listVO.getTerm()).getText());
                records.add(listVO);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        int pages = (int)(total+ searchDTO.getPageSize()-1)/searchDTO.getPageSize();
        pages = pages > 100 ? 100 : pages;
        return PageVO.build(searchDTO.getPageNo(),searchDTO.getPageSize(),total,pages,records);
    }
}
